#pragma once
#include <iostream>
#include <functional>
#include <pthread.h>
#include <unordered_map>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstring>
#include "sock.hpp"

#define READ_EVENT (0x1)
#define WRITE_EVENT (0x1 << 1)
#define EXCEPT_EVENT (0x1 << 2)

typedef struct FdEvent
{
  int fd;
  uint8_t event;
  std::string clientip;
  uint16_t clientport;
} FdEvent;
class SelectServer
{
  static const int N = sizeof(fd_set) * 8;
  static const int defaultfd = -1;
  static const uint8_t defaultevent = 0;

public:
  SelectServer(uint16_t port) : _port(port)
  {
    _map["hello"]="你好";
  }
  void InitServer()
  {
    _sock.Socket();
    _sock.Bind(_port);
    _sock.Listen();
    for (int i = 0; i < N; i++)
    {
      _fdarr[i].fd = defaultfd;
      _fdarr[i].event = defaultevent;
      _fdarr[i].clientport = 0;
    }
  }
  void Accepter()
  {
    std::string clientip;
    uint16_t clientport;
    int sock = _sock.Accept(&clientip, &clientport);
    if (sock < 0)
    {
      return;
    }
    // 获得了sock，将sock交给select，让select进行管理
    int pos = 1;
    for (; pos < N; pos++)
    {
      if (_fdarr[pos].fd == defaultfd)
      {
        break;
      }
    }
    if (pos >= N)
    {
      close(sock);
      std::cout << "sockfd array[] full\n";
    }
    else
    {
      _fdarr[pos].fd = sock;
      _fdarr[pos].event = READ_EVENT;
      _fdarr[pos].clientip = clientip;
      _fdarr[pos].clientport = clientport;
    }
  }
  void Recver(int index)
  {
    int fd = _fdarr[index].fd;
    char buffer[1024];
    ssize_t s = recv(fd, buffer, sizeof(buffer) - 1, 0);
    if (s > 0)
    {
      buffer[s - 1] = 0;
      std::cout << _fdarr[index].clientip << ":" << _fdarr[index].clientport << "# " << buffer << std::endl;

      // 发送回去也要被select管理的,TODO
      std::string key = buffer;
      std::string message;
      if(_map.find(key)==_map.end())
      {
        message="no find\n";
      }
      else
      {
        message=_map[buffer];
      }
      send(fd, message.c_str(), message.size(), 0);
    }
    else
    {
      if (s == 0)
        std::cout << "client quit ... , fdarray_[i] -> defaultfd: " << fd << "->" << defaultfd << std::endl;
      else
        std::cout << "recv error, client quit ... , fdarray_[i] -> defaultfd: " << fd << "->" << defaultfd << std::endl;
      close(_fdarr[index].fd);
      _fdarr[index].fd = defaultfd;
      _fdarr[index].event = defaultevent;
      _fdarr[index].clientip.resize(0);
      _fdarr[index].clientport = 0;
    }
  }
  void HandlerEvent(fd_set &rfds, fd_set &wfds)
  {
    for (int i = 0; i < N; i++)
    {
      if (_fdarr[i].fd == defaultfd)
      {
        continue;
      }
      if ((_fdarr[i].event & READ_EVENT) && (FD_ISSET(_fdarr[i].fd, &rfds)))
      {
        if (_fdarr[i].fd == _sock.GetFd())
        {
          Accepter();
        }
        else if (_fdarr[i].fd != _sock.GetFd())
        {
          Recver(i);
        }
        else
        {
        }
      }
      else if ((_fdarr[i].event & WRITE_EVENT) && (FD_ISSET(_fdarr[i].fd, &wfds)))
      {
        // TODO
      }
      else
      {
      }
    }
  }

  void Start()
  {
    _fdarr[0].fd = _sock.GetFd();
    _fdarr[0].event = READ_EVENT;
    while (true)
    {
      fd_set rfds;
      fd_set wfds;
      FD_ZERO(&rfds);
      FD_ZERO(&wfds);
      int maxfd = _fdarr[0].fd;
      for (int i = 0; i < N; i++)
      {
        if (_fdarr[i].fd == defaultfd)
        {
          continue;
        }
        if (_fdarr[i].event & READ_EVENT)
        {
          FD_SET(_fdarr[i].fd, &rfds);
        }
        if (_fdarr[i].event & WRITE_EVENT)
        {
          FD_SET(_fdarr[i].fd, &wfds);
        }
        if (maxfd < _fdarr[i].fd)
        {
          maxfd = _fdarr[i].fd;
        }
      }
      int n = select(maxfd + 1, &rfds, &wfds, nullptr, nullptr);
      switch (n)
      {
      case 0:
        std::cout << "timeout" << errno << strerror(errno) << std::endl;
        break;
      case -1:
        std::cout << errno << strerror(errno) << std::endl;
        break;
      default:
        std::cout << "有一个就绪事件发生" << std::endl;
        HandlerEvent(rfds, wfds);
        break;
      }
    }
  }

private:
  xjc::Sock _sock;
  uint16_t _port;
  FdEvent _fdarr[N]; // 管理所有fd
  std::unordered_map<std::string, std::string> _map;
};
